package cn.derry.servlet;

import cn.derry.domain.Account;
import cn.derry.domain.MessageForm;
import cn.derry.server.ChatServer;
import cn.derry.util.GetHttpSessionConfigurator;
import com.alibaba.fastjson.JSONObject;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.rmi.Naming;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author MangoDai
 * @decription ws服务
 * @date 2017/12/20
 **/
@ServerEndpoint(value = "/websocket", configurator = GetHttpSessionConfigurator.class)
public class WebSocket {
    private static final String SEND_METHOD = "send";
    private static final String RECEIVE_METHOD = "receive";

    /**
     * 在线人数
     */
    private static AtomicInteger socketCount = new AtomicInteger();

    /**
     * 在线的用户
     */
    private static ConcurrentHashMap<String, WebSocket> map = new ConcurrentHashMap<>();

    /**
     * 当前的用户session
     */
    private Session currentUser = null;

    private Account account = null;

    private long lastMessageTime = 0;

    @OnMessage
    public void onMessage(String message, Session session) {
        JSONObject jsonObject = JSONObject.parseObject(message);
        MessageForm form = creatMessageForm(jsonObject);
        /**
         * 如果不是同一个人发送者,有人暴力入侵
         */
        if (!account.getId().equals(form.getFrom())) {
            sendMessage(account.getId(), account.getId(), " 在伪装别人发送消息");
        } else {
            if (SEND_METHOD.equals(form.getMethod())) {
                send(form.getTo(), form.getContent());
            } else {
                // 有人自己发表单
                sendMessage(account.getId(), account.getId(), " 在自己发假的socket请求");
            }
        }
    }


    /**
     * websocket 重头戏
     *
     * @param to
     * @param message
     * @return
     */

    protected String send(String to, String message) {
        String str;
        if (lastMessageTime == 0 || (System.currentTimeMillis() - lastMessageTime) > 1000) {
            lastMessageTime = System.currentTimeMillis();
            str = "发送 " + account.getUsername() + " 给 " + to + " 的消息";
            ChatServer.saveChatRecord(account.getId(), to, message);
            WebSocket recevier = map.get(to);
            if (recevier != null) {
                recevier.sendMessage(account.getId(), to, message);
            }
        } else {
            str = account.getId() + " 发送给 " + to + " 的消息 太快了，以至于被取消";
        }
        System.out.println(str);
        return str;
    }

    public MessageForm creatMessageForm(JSONObject jsonObject) {
        String method = (String) jsonObject.get("method");
        String from = (String) jsonObject.get("from");
        String to = (String) jsonObject.get("to");
        String content = (String) jsonObject.get("content");
        return new MessageForm(from, to, content, method);
    }


    public void sendMessage(String from, String to, String message) {
        try {
            this.currentUser.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("发送消息产生了错误 从 " + from + " 到 " + to + "  " + e.getMessage());
        }
    }

    /**
     * 新加入的socket
     *
     * @param session 用户
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        account = (Account) httpSession.getAttribute(LoginServlet.SESSION_USER);
        if (null == this.account) {
            sendMessage(account.getUsername(), "链接中", "小样，没有登陆就想链接");
        } else {
            WebSocket.map.put(account.getId(), this);
            currentUser = session;
        }
        System.out.println("当前的 websocket 加入 ，当前人数为 " + socketCount.incrementAndGet());
    }

    /**
     * 新关闭的socket
     */
    @OnClose
    public void onClose() {
        if (account != null) {
            WebSocket.map.remove(account.getId());
        }
        System.out.println("当前有 websocket 关闭，当前人数为 " + socketCount.decrementAndGet());
    }

    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生了不可预知的错误 session = " + session);
        error.printStackTrace();
    }

}
